package com.itfetter.trade.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.itfetter.api.client.CartClient;
import com.itfetter.api.client.ItemClient;
import com.itfetter.api.dto.ItemDTO;
import com.itfetter.api.dto.OrderDetailDTO;
import com.itfetter.common.exception.BadRequestException;
import com.itfetter.common.utils.UserContext;
import com.itfetter.trade.domain.dto.OrderFormDTO;
import com.itfetter.trade.domain.po.Order;
import com.itfetter.trade.domain.po.OrderDetail;
import com.itfetter.trade.mapper.OrderMapper;
import com.itfetter.trade.service.IOrderDetailService;
import com.itfetter.trade.service.IOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 羁绊
 * @since 2023-05-05
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    private final ItemClient itemClient;
    private final IOrderDetailService detailService;
    private final CartClient cartClient;
    private final RocketMQTemplate rocketMQTemplate;

    @Override
    @GlobalTransactional
    public Long createOrder(OrderFormDTO orderFormDTO) {
        // 1.订单数据
        Order order = new Order();
        // 1.1.查询商品
        List<OrderDetailDTO> detailDTOS = orderFormDTO.getDetails();
        // 1.2.获取商品id和数量的Map
        Map<Long, Integer> itemNumMap = detailDTOS.stream()
                .collect(Collectors.toMap(OrderDetailDTO::getItemId, OrderDetailDTO::getNum));
        Set<Long> itemIds = itemNumMap.keySet();
        // 1.3.查询商品
        List<ItemDTO> items = itemClient.queryItemByIds(itemIds);
        if (items == null || items.size() < itemIds.size()) {
            throw new BadRequestException("商品不存在");
        }
        // 1.4.基于商品价格、购买数量计算商品总价：totalFee
        int total = 0;
        for (ItemDTO item : items) {
            total += item.getPrice() * itemNumMap.get(item.getId());
        }
        order.setTotalFee(total);
        // 1.5.其它属性
        order.setPaymentType(orderFormDTO.getPaymentType());
        order.setUserId(UserContext.getUser());
        order.setStatus(1);
        // 1.6.将Order写入数据库order表中
        save(order);

        // 2.保存订单详情
        List<OrderDetail> details = buildDetails(order.getId(), items, itemNumMap);
        detailService.saveBatch(details);

        // 3.清理购物车商品
//        cartClient.deleteCartItemByIds(itemIds);
//        Map<String, Object> message = new HashMap<>();
//        message.put("user-info", UserContext.getUser());
//        message.put("items", items);
        Message<List<ItemDTO>> message = new Message<List<ItemDTO>>() {
            @Override
            public List<ItemDTO> getPayload() {
                return items;
            }

            @Override
            public MessageHeaders getHeaders() {
                Map<String, Object> map = new HashMap<>();
                map.put("userId", UserContext.getUser());
                MessageHeaders messageHeaders = new MessageHeaders(map);
                return messageHeaders;
            }
        };
        rocketMQTemplate.asyncSend("cart-clear", message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                log.info("用户下单成功，开始清空购物车");
            }

            @Override
            public void onException(Throwable throwable) {
                log.info("发送消息失败，清空购物车失败");
                throwable.printStackTrace();
            }
        });

        // 4.扣减库存
        try {
            itemClient.deductStock(detailDTOS);
        } catch (Exception e) {
            throw new RuntimeException("库存不足！");
        }
//        Message<String> message2=new Message<String>() {
//            @Override
//            public String getPayload() {
//                return "1";
//            }
//
//            @Override
//            public MessageHeaders getHeaders() {
//                Map<String,Object> map=new HashMap<>();
//                map.put("userId",UserContext.getUser());
//                MessageHeaders messageHeaders=new MessageHeaders(map);
//                return null;
//            }
//        };
        Map<String, Object> map = new HashMap<>();
        map.put("bizOrderNo", order.getId());
        Message message1 = MessageBuilder.createMessage(1, new MessageHeaders(map));

        try {
            rocketMQTemplate.syncSend("paydelay", message1, 1000, 1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return order.getId();
    }

    @Override
    public void markOrderPaySuccess(Long orderId) {
        Order order = new Order();
        order.setId(orderId);
        order.setStatus(2);
        order.setPayTime(LocalDateTime.now());
        updateById(order);
    }

    /**
     * 根据订单id取消订单
     *
     * @param orderId 订单id
     */
    @Override
    public void cancelOrder(Long orderId) {
        Order order = getById(orderId);
        if (order == null || order.getStatus() == 3) {
            return;
        }
        //修改订单状态成订单已取消交易关闭，
        order.setStatus(5);
        updateById(order);
    }

    private List<OrderDetail> buildDetails(Long orderId, List<ItemDTO> items, Map<Long, Integer> numMap) {
        List<OrderDetail> details = new ArrayList<>(items.size());
        for (ItemDTO item : items) {
            OrderDetail detail = new OrderDetail();
            detail.setName(item.getName());
            detail.setSpec(item.getSpec());
            detail.setPrice(item.getPrice());
            detail.setNum(numMap.get(item.getId()));
            detail.setItemId(item.getId());
            detail.setImage(item.getImage());
            detail.setOrderId(orderId);
            details.add(detail);
        }
        return details;
    }
}
